<?php

declare(strict_types=1);

namespace App\CustHub\Work;

use App\CustHub\Interfaces\OpenWorkAccountInterface;
use App\CustHub\Mapper\ChOpenWorkAgentMapper;
use App\CustHub\Utils\OpenWorkAppUtil;
use EasyWeChat\Kernel\Contracts\AccessToken as AccessTokenInterface;
use EasyWeChat\Kernel\HttpClient\AccessTokenAwareClient;
use EasyWeChat\Kernel\HttpClient\Response;
use EasyWeChat\Kernel\Traits\InteractWithClient;
use EasyWeChat\Kernel\Traits\InteractWithHttpClient;
use EasyWeChat\Kernel\Traits\InteractWithServerRequest;
use EasyWeChat\OpenWork\Contracts\SuiteTicket as SuiteTicketInterface;
use EasyWeChat\OpenWork\SuiteAccessToken;
use EasyWeChat\OpenWork\SuiteTicket;
use Hyperf\Config\Config;
use Hyperf\Contract\ConfigInterface;
use Mine\Exception\NormalStatusException;
use Psr\SimpleCache\CacheInterface;
use function Hyperf\Collection\collect;

class TxlApiService
{
    use InteractWithClient;
    use InteractWithHttpClient;
    use InteractWithServerRequest;

    protected ConfigInterface $config;

    protected CacheInterface $cache;

    protected ?OpenWorkAccountInterface $account = null;

    protected ?AccessTokenInterface $suiteAccessToken = null;

    protected ?SuiteTicketInterface $suiteTicket = null;

    protected mixed $agentId;


    public function __construct(string $authCorpId)
    {
        $agentInfo = container()->get(ChOpenWorkAgentMapper::class)->getInfoByCorpid($authCorpId);
        $this->agentId = $agentInfo->id;

        $config = container()->get(ConfigInterface::class)->get('wechat.wework');
        $config['corp_id'] = $agentInfo->wx_corpid;
        $config['provider_secret'] = $agentInfo->txl_secret;
        [$suiteId, $suiteSecret] = OpenWorkAppUtil::getSuiteIdAndSuiteSecret();
        $config['suite_id'] = 'ww40ecd746c63396c1';
        $config['suite_secret'] = 'jtDEEepo24BHBv7NfWnfxVAu2VnnvM73HOcVXhrcNwg';
        $this->config = new Config($config);
        $this->cache = container()->get(CacheInterface::class);
    }

    public function getAccount(): OpenWorkAccount
    {
        if (! $this->account) {
            $this->account = new OpenWorkAccount(
                corpId: (string) $this->config->get('corp_id'), /** @phpstan-ignore-line */
                providerSecret: (string) $this->config->get('provider_secret'), /** @phpstan-ignore-line */
                suiteId: (string) $this->config->get('suite_id'), /** @phpstan-ignore-line */
                suiteSecret: (string) $this->config->get('suite_secret'), /** @phpstan-ignore-line */
            );
        }

        return $this->account;
    }

    public function createClient(): AccessTokenAwareClient
    {
        return (new AccessTokenAwareClient(
            client: $this->getHttpClient(),
            accessToken: $this->getAuthorizerAccessToken(),
            failureJudge: fn (Response $response) => (bool) ($response->toArray()['errcode'] ?? 0),
            throw: (bool) $this->config->get('http.throw', true),
        ))->setPresets(collect($this->config)->toArray());
    }

    public function getAuthorizerAccessToken(): TxlAccessToken {
        return new TxlAccessToken(
            corpId: $this->getAccount()->getCorpId(),
            corpSecret: $this->getAccount()->getProviderSecret(),
            suiteAccessToken: $this->getSuiteAccessToken(),
            cache: $this->cache,
            httpClient: $this->getHttpClient(),
        );
    }

    public function getSuiteAccessToken(): AccessTokenInterface
    {
        if (! $this->suiteAccessToken) {

            $this->suiteAccessToken = new SuiteAccessToken(
                suiteId: $this->getAccount()->getSuiteId(),
                suiteSecret: $this->getAccount()->getSuiteSecret(),
                suiteTicket: $this->getSuiteTicket(),
                cache: $this->cache,
                httpClient: $this->getHttpClient(),
            );
        }

        return $this->suiteAccessToken;
    }

    public function getSuiteTicket(): SuiteTicketInterface
    {
        if (! $this->suiteTicket) {
            $this->suiteTicket = new SuiteTicket(
                suiteId: $this->getAccount()->getSuiteId(),
                cache: $this->cache,
                key: 'txlSuiteTicket:' . $this->getAccount()->getSuiteId()
            );
        }
        return $this->suiteTicket;
    }

    /**
     * @return array<string, mixed>
     */
    protected function getHttpClientDefaultOptions(): array
    {
        return array_merge(
            ['base_uri' => 'https://qyapi.weixin.qq.com/'],
            (array) $this->config->get('http', [])
        );
    }

    /**
     * 获取成员ID列表
     * @param string $cursor
     * @param int $limit
     * @return array
     */
    public function getUserIdList(string $cursor = '',int $limit = 1000): array
    {
        $response = $this->requestPost('cgi-bin/user/list_id',[
            'cursor' => $cursor,
            'limit' => $limit
        ]);
        return $response;
    }

    public function getUserListByDeptId(int $deptId)
    {
        $response = $this->getClient()->request('GET','cgi-bin/user/simplelist',[
            'query' => [
                'department_id' => $deptId,
                'debug' => 1
            ]
        ])->toArray(false);
    }

    public function requestPost(string $url,array $data): array
    {
        $response = $this->getClient()->request('POST', $url, [
            'json' => $data,
        ])->toArray(false);

        if(isset($response['errcode']) && $response['errcode'] !== 0){
            logger()->info($url.'请求失败，错误信息：'.$response['errmsg']);
            throw new NormalStatusException($url.'请求失败，错误信息：'.$response['errmsg']);
        }
        return $response;
    }

}